`default_nettype none

module edge_counter_clk_m #(
    parameter [0:0] BEFORE_EDGE_CP_I = 0,
    parameter [31:0] MUL_CP_I = 1,
    parameter [31:0] DIV_CP_I = 3,

    localparam [31:0] COUNTER_WIDTH_CP_L = $clog2(MUL_CP_I + DIV_CP_I)
) (
    input rst_w_ni,
    input clk_w_i,
    input [COUNTER_WIDTH_CP_L-1:0] counterpart_wp_i,

    output [COUNTER_WIDTH_CP_L-1:0] counter_wp_o,
    output edge_clk_w_o
);
    wire [COUNTER_WIDTH_CP_L-1:0] set_counter_wp_l;
    wire [COUNTER_WIDTH_CP_L-1:0] counter_if_add_wp_l =
        counter_wp_o + counterpart_wp_i + MUL_CP_I;
    wire set_edge_clk_w_l;
    assign {set_counter_wp_l, set_edge_clk_w_l} =
        (counter_if_add_wp_l >= DIV_CP_I) ?
        {counter_wp_o + MUL_CP_I - DIV_CP_I, ~edge_clk_w_o} :
        {counter_wp_o + MUL_CP_I, edge_clk_w_o};

    gen_dreg_m #(
        .BEFORE_EDGE_CP_I(BEFORE_EDGE_CP_I),
        .WIDTH_CP_I(COUNTER_WIDTH_CP_L + 1),
        .INIT_VALUE_CP_I(0)
    ) dreg_i_l (
        .rst_w_ni(rst_w_ni),
        .clk_w_i(clk_w_i),
        .set_en_w_pi(1),
        .set_wp_i({set_counter_wp_l, set_edge_clk_w_l}),

        .get_wp_o({counter_wp_o, edge_clk_w_o})
    );
endmodule
